<?php
class uploader
{
	private $simcaps;
	private $convert = 'convert';
	const ASSET_TEXTURE = 'texture';
	const ASSET_SOUND = 'sound';
	// WARNING: Animation upload is not currently working.
	const ASSET_ANIMATION = 'animatn';
	const INVENTORY_TEXTURE = 'texture';
	const INVENTORY_SOUND = 'sound';
	const INVENTORY_ANIMATION = 'animation';
	
	private function _uploadcheck()
	{
		if(!is_object($this->simcaps))
		{
			return false;
		}
		if(!$this->simcaps->loggedin())
		{
			return $this->simcaps->login();
		}
		return true;
	}
	
	private function _uploadinventory($inventory, $asset, $name, $description, $data, LLUUID $folderid)
	{
		$request = array(
			'asset_type' => $asset,
			'description' => $description,
			'folder_id' => $folderid->tostring(),
			'inventory_type' => $inventory,
			'name' => $name
		);
		$this->simcaps->_debug(print_r($request,true),5);
		$response = $this->simcaps->sendrequest('NewFileAgentInventory',$request);
		$this->simcaps->_debug(print_r($response,true),5);
		if('upload' == $response['state'])
		{
			$result = $this->simcaps->sendrawdata($response['uploader'],$data);
			$this->simcaps->_debug(print_r($result,true),5);
			if($result['state'] == 'complete')
			{
				return new LLUUID($result['new_asset']);
			}
			else
			{
				return new LLUUID();
			}
		}
		else
		{
			$this->simcaps->_debug(print_r($response,true),4);
			return new LLUUID();
		}
		
	}
	
	public function __construct(simcaps $simcaps)
	{
		$this->simcaps = $simcaps;
	}
	
	public function setconvert($path)
	{
		$this->convert = $path;
	}
	
	public function uploadtexture($filename, $name, $description, $targetfolder = '/Textures', $quality = 100)
	{
		if(!$this->_uploadcheck())
		{
			return new LLUUID();
		}
		if(!file_exists($filename))
		{
			return new LLUUID();
		}
		$folderid = $this->simcaps->getfolderid($targetfolder);
		if(new LLUUID() == $folderid)
		{
			return new LLUUID();
		}
		//$size = getimagesize($filename);
		$size = explode(' ',exec('identify '.escapeshellarg($filename)));
		$size = explode('x',$size[2]);
		$x = pow(2,round(log($size[0],2)));
		$y = pow(2,round(log($size[1],2)));
		$resizing = false;
		if($x != $size[0] || $y != $size[1])
		{
			$this->simcaps->_debug("Resizing image to {$x}x{$y}",4);
			$resizing = true;
		}
		$quality = (int)$quality;
		exec("{$this->convert} ".escapeshellarg($filename)." ".($resizing?"-resize {$x}x{$y}! ":'')."-quality {$quality} temp.jpc");
		$response = $this->_uploadinventory(self::INVENTORY_TEXTURE, self::ASSET_TEXTURE, $name, $description, file_get_contents('temp.jpc'), $folderid);
		@unlink('temp.jpc');
		return $response;
	}
	
	public function uploadanim($filename, $name, $description, $targetfolder = '/Animations'/*, some other arguments */)
	{
		if(!$this->_uploadcheck())
		{
			return new LLUUID();
		}
		if(!file_exists($filename))
		{
			return new LLUUID();
		}
		$folderid = $this->simcaps->getfolderid($targetfolder);
		if(new LLUUID() == $folderid)
		{
			return new LLUUID();
		}
		return $this->_uploadinventory(self::INVENTORY_ANIMATION, self::ASSET_ANIMATION, $name, $description, file_get_contents($filename), $targetfolder);
	}
	
	// Should add support for tools such as oggenc for converting from wav.
	public function uploadsound($filename, $name, $description, $targetfolder = '/Sounds'/*, Quality, etc. */)
	{
		if(!$this->_uploadcheck())
		{
			$this->simcaps->_debug("Not yet logged in.",1);
			return new LLUUID();
		}
		if(!file_exists($filename))
		{
			$this->simcaps->_debug("No such file.",1);
			return new LLUUID();
		}
		$folderid = $this->simcaps->getfolderid($targetfolder);
		if($folderid == new LLUUID() || $folderid == NULL)
		{
			$this->simcaps->_debug("Missing folder",1);
			return new LLUUID();
		}
		return $this->_uploadinventory(self::INVENTORY_SOUND, self::ASSET_SOUND, $name, $description, file_get_contents($filename), $folderid);
	}
}

// This can only be used to edit notecards with known UUIDs. Since we can't get inventory keys, how you know this is a mystery.
// However, LSL scripts can get the keys of notecards in objects, so perhaps this could be used for an llWriteNotecard type thing...
class notecard
{
	private $text = '';
	private $simcaps;
	const MAX_LENGTH = 32768; // Max character count. (Or is it bytes? Should check that)

	private function _exportnote($text)
	{
		$notecard  = "Linden text version 2\n";
		$notecard .= "{\n";
		$notecard .= "Text length ".strlen($text)."\n";
		$notecard .= $text;
		$notecard .= "}\n";
		return $notecard;
	}

	public function __construct(simcaps $simcaps)
	{
		$this->simcaps = $simcaps;
		$this->uuid = $uuid;
	}
	
	public function settext($text)
	{
		if(strlen($text) > self::MAX_LENGTH)
		{
			$this->simcaps->_debug("notecard::settext call exceeds mac length of ".self::MAX_LENGTH." bytes.",2);
			return false;
		}
		else
		{
			$this->text = $text;
		}
	}
	
	public function gettext()
	{
		return $text;
	}
	
	public function save(LLUUID $uuid, LLUUID $item = null)
	{
		$note = $this->_exportnote($text);
		$results = array();
		if(new LLUUID() != $item)
		{
			if(!$this->simcaps->hascapability('UpdateNotecardAgentInventory'))
			{
				$simcaps->_debug("notecard::save failed due to the UpdateNotecardAgentInventory capability being inactive.");
				return false;
			}
			$request = array(
				'item_id' => $uuid->tostring()
			);
			$results = $this->simcaps->sendrequest('UpdateNotecardAgentInventory',$request);
		}
		else
		{
			if(!$this->simcaps->hascapability('UpdateNotecardTaskInventory'))
			{
				$simcaps->_debug("notecard::save failed due to the UpdateNotecardTaskInventory capability being inactive.");
				return false;
			}
			$request = array(
				'item_id' => $uuid->tostring(),
				'task_id' => $item->tostring()
			);
			$results = $this->simcaps->sendrequest('UpdateNotecardTaskInventory',$request);
		}
		if(isset($results['state']) && $results['state'] == 'upload')
		{
			$this->print_r($this->simcaps->sendrawdata($results['uploader'],$note));
			return true;
		}
		$this->simcaps->_debug(print_r($results,true),2);
		return false;
	}
}
?>
